home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / Gps Folder / gps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-14  |  18.3 KB  |  761 lines  |  [TEXT/KAHL]

  1. /* GPS program by Glen Lalonde, glalonde@vnet.ibm.com */
  2.  
  3.  
  4. #include <processes.h>
  5. #include <gestaltequ.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9.  
  10.  
  11. WindowPtr theWindow, statsWindowPtr;
  12. Rect drawbound,dragbound,limitRect;
  13. WindowRecord windowRcd, statsWindowRcd;
  14. EventRecord theEvent;
  15.  
  16. short selectedProcess =0;
  17. char autoRefresh =0;
  18.  
  19. #define maxProcs 50
  20.  
  21. #define windowWidth  285
  22. #define stepsPerScreen 10
  23. #define topInset 10
  24. #define bottomInset 10
  25. #define zoomInDir 1
  26.  
  27. #define appleMenuNum 127
  28. #define fileMenuNum 128
  29. #define zoomMenuNum 129
  30. #define refreshMenuNum 130
  31.  
  32. ProcessInfoRec InfoRec[maxProcs];
  33. ProcessInfoRec *(InfoRecPtr[maxProcs]);
  34. long screenOrg[700];
  35.  
  36. unsigned long zoomFactor = 1;
  37.  
  38. RgnHandle updateRgn;
  39.  
  40. long absBottom, absTop;
  41. long graphRange, graphBottom, scrollRange;
  42. long scaleFactor;
  43. long memSize;
  44. long windowLength;
  45. Rect frameRect, ctrlRect;
  46. unsigned long currentPos;
  47. MenuHandle fileMenu, zoomMenu, appleMenu, refreshMenu;
  48. long graphVertOffset =0;
  49.  
  50.  
  51. long numProcs;
  52. ControlHandle scrollBarCtl, nextButton, prevButton;
  53.  
  54.  
  55. /* functions */
  56. void makeWindow(void);
  57. void readProcTable(void);
  58. void sortProcTable(void);
  59. void drawMemDiagram(void);
  60. void sizeSetup(void);
  61. void eventLoop(void);
  62. void refreshDiagram(int, int);
  63. void menuEvent(unsigned long);
  64. void aboutBox();
  65. void drawStatsWindow(void);
  66. void mouseDownInStats(int);
  67. void mouseDownInGraph(int);
  68. void setupMenus(void);
  69. void refreshStats(void);
  70. pascal void updateAction(ControlHandle theControl, int partCode);
  71. void mouseDownEvent(void);
  72. void zoom(char direction);
  73. void aboutBox(void);
  74. void refreshProcTable(void);
  75.  
  76.  
  77. Str255 appleTitle = { 1, appleMark };
  78.  
  79. void setupMenus(void) {
  80.     appleMenu = NewMenu(appleMenuNum, appleTitle);
  81.     fileMenu = NewMenu(fileMenuNum, "\pFILE");
  82.     zoomMenu = NewMenu(zoomMenuNum, "\pZOOM");
  83.     refreshMenu = NewMenu(refreshMenuNum, "\pRefresh");
  84.   
  85.     AppendMenu(appleMenu, "\PAbout GPS...");
  86.     AppendMenu(appleMenu, "\p-");
  87.     AddResMenu(appleMenu, 'DRVR');
  88.     AppendMenu(fileMenu, "\pQuit/Q");
  89.     AppendMenu(zoomMenu, "\pIn/I");
  90.     AppendMenu(zoomMenu, "\pOut/O");
  91.   
  92.       
  93.       AppendMenu(refreshMenu, "\pRefresh Now/R");
  94.      AppendMenu(refreshMenu, "\pAuto Refresh");
  95.   
  96.       InsertMenu(appleMenu,0);  
  97.     InsertMenu(fileMenu,0);
  98.     InsertMenu(zoomMenu,0);
  99.     InsertMenu(refreshMenu, 0);
  100.   
  101.     DrawMenuBar();
  102. }
  103.  
  104.  
  105. void main(void)
  106. {
  107.     InitGraf(&thePort);
  108.     InitFonts();
  109.     InitWindows();
  110.     InitCursor();
  111.     InitMenus();
  112.     InitDialogs(NULL);
  113.     PenNormal();
  114.     TextSize(0);
  115.     TextMode(srcOr);
  116.     FlushEvents( everyEvent, 0 );
  117.  
  118.     readProcTable(); /* read all the process information */
  119.     sortProcTable(); /* ensure it is in the correct order */
  120.   
  121.     setupMenus();
  122.  
  123.     windowLength = screenBits.bounds.bottom-50;
  124.     absBottom = windowLength;
  125.     DisableItem(zoomMenu ,2);
  126.   
  127.     Gestalt(gestaltLogicalRAMSize, &memSize);
  128.   
  129.     SetRect(&frameRect, 0, 200,100,400);
  130.   
  131.     sizeSetup();
  132.   
  133.     updateRgn = NewRgn();
  134.     
  135.     makeWindow();
  136.     TextSize(9);
  137.   
  138.       drawStatsWindow();
  139.     drawMemDiagram(); /* draw diagram of memory use */
  140.     
  141.     eventLoop(); /* main event loop */            
  142. }
  143.  
  144.  
  145. void refreshDiagram(int old, int new) {
  146.     Rect clearRect;
  147.     unsigned long newTop = screenOrg[new];
  148.     unsigned long oldTop = screenOrg[old];
  149.   
  150.     if (old == new) return; /* no need to update */
  151.    
  152.     SetEmptyRgn(updateRgn);
  153.    
  154.     graphVertOffset = newTop; 
  155.  
  156.     SetRect(&clearRect, 0, 0, windowWidth-16, +windowLength);
  157.              
  158.     /* scroll the old data in the window */          
  159.     ScrollRect(&clearRect, 0, (newTop-oldTop), updateRgn);
  160.  
  161.     InvalRgn(updateRgn);    /* indicate part of window that needs update */         
  162.  
  163.     drawMemDiagram();      /* draw the conents of the window */
  164. }
  165.     
  166.     
  167. void refreshStats(void) {
  168.     Rect theRect;
  169.     
  170.     SetRect(&theRect, 0,0, 200,300);
  171.     FillRect(&theRect,white);
  172.   
  173.     InvalRect(&theRect);
  174.     drawStatsWindow();
  175. }
  176.    
  177.     
  178. pascal void updateAction(ControlHandle theControl, int partCode) {
  179.    short current;
  180.    short newCtlValue;
  181.    
  182.    current = GetCtlValue(theControl);
  183.    
  184.    switch(partCode) {
  185.       case inUpButton: newCtlValue = (current == 0 ? 0 : current-1); break;
  186.       case inPageUp:
  187.             newCtlValue = ((current - stepsPerScreen) < 0 ? 0 :
  188.                            (current - stepsPerScreen));
  189.             break;
  190.       case inDownButton:
  191.             newCtlValue = (current == scrollRange ? scrollRange :
  192.                                                       current +1); 
  193.             break;
  194.       case inPageDown:
  195.             newCtlValue = ((current + stepsPerScreen) > scrollRange ? 
  196.                            scrollRange : (current + stepsPerScreen));
  197.             break;
  198.       default: ;
  199.    }
  200.    
  201.    if (current != newCtlValue)  { 
  202.        SetCtlValue(theControl, newCtlValue);
  203.        refreshDiagram(current, GetCtlValue(theControl));
  204.    }
  205.    
  206. }
  207.    
  208.    
  209. void mouseDownEvent(void) {
  210.     WindowPtr whichWindow;
  211.     int part;
  212.     ControlHandle whichControl;
  213.         
  214.     part = FindWindow(theEvent.where, &whichWindow);
  215.          
  216.     if (part == inMenuBar)  { 
  217.         menuEvent(MenuSelect(theEvent.where));
  218.         return;
  219.     }
  220.     
  221.     if (part == inSysWindow) {
  222.         SystemClick(&theEvent, whichWindow);
  223.         return;
  224.     }
  225.     
  226.     if (FrontWindow() != whichWindow) {
  227.         SelectWindow(whichWindow); return;
  228.     }
  229.     
  230.     if (whichWindow == theWindow)  mouseDownInGraph(part);
  231.     if (whichWindow == statsWindowPtr) mouseDownInStats(part);
  232. }
  233.  
  234.  
  235. void mouseDownInGraph(int thePart) {
  236.     int part;
  237.     ControlHandle whichControl;
  238.     int oldVal, res;
  239.              
  240.     switch(thePart) {
  241.         case inContent:
  242.         case inGrow:
  243.             GlobalToLocal(&theEvent.where);
  244.                 
  245.             part = FindControl(theEvent.where, theWindow, &whichControl);
  246.                  
  247.             switch(part) { 
  248.                 case inThumb:
  249.                     oldVal = GetCtlValue(scrollBarCtl);
  250.                     res = TrackControl(scrollBarCtl, theEvent.where, NULL);                         
  251.                     if (res) refreshDiagram(oldVal, GetCtlValue(scrollBarCtl));
  252.                 break;
  253.                 case inUpButton:
  254.                 case inDownButton:
  255.                 case inPageUp:
  256.                    case inPageDown:
  257.                     TrackControl(scrollBarCtl, theEvent.where, updateAction);
  258.                 break;
  259.                 default: ;
  260.             }
  261.         break;
  262.         case inGoAway:
  263.             if (TrackGoAway(theWindow, theEvent.where)) ExitToShell();
  264.         break;
  265.         case inDrag: {
  266.             Rect boundsRect;
  267.             SetRect(&boundsRect, 4, 20, 510, 340); /* calc Correct values later */
  268.             DragWindow(theWindow, theEvent.where, &boundsRect);
  269.             }
  270.            break;
  271.                  
  272.            default :;
  273.     }            
  274. }
  275.  
  276.  
  277. void mouseDownInStats(int thePart) { 
  278.     int part, res;
  279.     ControlHandle whichControl;
  280.              
  281.     switch(thePart) {
  282.         case inContent:
  283.         case inGrow:
  284.             GlobalToLocal(&theEvent.where);
  285.                 
  286.             part = FindControl(theEvent.where, statsWindowPtr, &whichControl);
  287.         
  288.             switch(part) { 
  289.                 case inButton:
  290.                     res = TrackControl(whichControl, theEvent.where, pushButProc);
  291.                     if (res == inButton) {
  292.                        if (whichControl == prevButton) {
  293.                            if (selectedProcess !=0) {
  294.                                  selectedProcess--;
  295.                                  refreshStats();
  296.                            }
  297.                        }
  298.                        if (whichControl == nextButton) {
  299.                          if(selectedProcess != (numProcs-1)) {
  300.                              selectedProcess++;
  301.                              refreshStats();
  302.                           }
  303.                        }
  304.     
  305.                     }
  306.                 default: ;
  307.             }
  308.         break;
  309.         case inGoAway:
  310.         break;
  311.         case inDrag: {
  312.             Rect boundsRect;
  313.             SetRect(&boundsRect, 4, 20, 510, 340); /* calc Correct values later */
  314.             DragWindow(statsWindowPtr, theEvent.where, &boundsRect);
  315.             }
  316.                  
  317.            default :;
  318.     }            
  319. }
  320.  
  321.  
  322. void zoom(char direction) {
  323.      Rect badRect;
  324.  
  325.     if (direction == zoomInDir) {
  326.        if (zoomFactor < 32) zoomFactor <<=1;
  327.          else return;
  328.     } else {
  329.        if (zoomFactor > 1) zoomFactor >>=1;
  330.        else return;
  331.     }
  332.     
  333.     switch (zoomFactor) {
  334.        case 1: DisableItem(zoomMenu ,2);
  335.        break;
  336.        case 32: DisableItem(zoomMenu ,1);
  337.        break;
  338.        case 2: EnableItem(zoomMenu, 2);
  339.        break;
  340.        case 16: EnableItem(zoomMenu,1);
  341.        break;
  342.     }
  343.     
  344.     absBottom = zoomFactor*windowLength;
  345.     
  346.     sizeSetup();
  347.    
  348.     graphVertOffset = 0;
  349.     
  350.     /* remake control */
  351.     SetPort(&windowRcd.port);
  352.  
  353.     SetRect(&ctrlRect, windowWidth-16, 0, windowWidth, windowLength);
  354.     
  355.     DisposeControl(scrollBarCtl); 
  356.     scrollBarCtl = NewControl(theWindow, &ctrlRect, "\pControl", TRUE, 
  357.                                 0, 0, scrollRange, scrollBarProc, 0); 
  358.     
  359.     SetRect(&badRect, 0, 0, windowWidth, windowLength);
  360.     FillRect(&badRect, white); 
  361.     
  362.     InvalRect(&badRect);
  363.     drawMemDiagram();
  364.     
  365.     if (FrontWindow() != theWindow) HiliteControl(scrollBarCtl, 255);
  366.     SetPort(FrontWindow());
  367. }
  368.  
  369.  
  370. void aboutBox(void) { 
  371.     short itemHit;
  372.     DialogPtr aboutPtr;
  373.     
  374.     aboutPtr = GetNewDialog(128, NULL, (void *) -1);
  375.     if (aboutPtr != 0) ModalDialog(NULL, &itemHit);
  376.     DisposDialog(aboutPtr);
  377. }
  378.  
  379.  
  380. void refreshProcTable(void) {
  381.     Rect badRect, theRect;
  382.     WindowPtr frontWindow;
  383.     
  384.     frontWindow = FrontWindow();
  385.     
  386.     /* update tables from process manager */
  387.     readProcTable();
  388.     sortProcTable();
  389.     
  390.     /* graph window */
  391.     selectedProcess =0;
  392.     SetCtlValue(scrollBarCtl, 0);
  393.     graphVertOffset = 0;
  394.     
  395.     SetPort(&windowRcd.port);
  396.     
  397.     SetRect(&badRect, 0, 0, windowWidth, windowLength);
  398.     FillRect(&badRect, white); 
  399.     
  400.     InvalRect(&badRect);
  401.     drawMemDiagram();
  402.     
  403.     /* now handle the stats window */
  404.     SetPort(statsWindowPtr);
  405.     SetRect(&theRect, 0,0, 200,300);
  406.     FillRect(&theRect,white);
  407.  
  408.     InvalRect(&theRect);
  409.     drawStatsWindow();
  410.     
  411.     /* reset state */
  412.     SetPort(frontWindow);
  413. }
  414.  
  415.  
  416. void menuEvent(unsigned long menuSelected) {
  417.     unsigned char theItem = menuSelected & 0xFFFF;
  418.  
  419.     switch(menuSelected>>16) {
  420.         case fileMenuNum:
  421.             if (theItem == 1) { ExitToShell(); }        
  422.         break;
  423.         
  424.         case zoomMenuNum:
  425.             zoom(theItem);
  426.         break;
  427.         
  428.         case refreshMenuNum:
  429.             if (theItem == 1)  refreshProcTable();
  430.             if (theItem == 2) {
  431.                 autoRefresh = !autoRefresh;
  432.                 CheckItem(refreshMenu, 2, autoRefresh);
  433.             }
  434.         break;
  435.     
  436.         case appleMenuNum:
  437.             if (theItem == 1)  aboutBox();
  438.             else {
  439.                 Str255 accName;
  440.                 GetItem(appleMenu, theItem, accName);
  441.                 OpenDeskAcc(accName);
  442.             } 
  443.         default: ;
  444.     }
  445.     
  446.     HiliteMenu(0); 
  447. }
  448.  
  449.  
  450.  
  451. /* the Main event loop */
  452. void eventLoop(void) { 
  453.    int junk;
  454.    WindowPtr whichWindow;    
  455.     
  456.    do {
  457.       junk = WaitNextEvent( everyEvent, &theEvent, 120, NULL );
  458.       
  459.       switch(theEvent.what) {
  460.         case mouseDown: mouseDownEvent();
  461.             break;
  462.         case updateEvt:
  463.         #if 0
  464.             /* this method will cause a large delay in the update of the */
  465.             /* window */
  466.             FindWindow(theEvent.where, &whichWindow);             
  467.             if (whichWindow == theWindow) drawMemDiagram();
  468.             if (whichWindow == statsWindowPtr) drawStatsWindow();
  469.         #endif
  470.             /* MUST insure the correct graphPort is set at the end or */
  471.             /* our controls will fail */
  472.             drawMemDiagram();
  473.             drawStatsWindow();
  474.             SetPort(FrontWindow()) ;
  475.             break;
  476.         case keyDown:
  477.             if (theEvent.modifiers && cmdKey)  
  478.                  menuEvent(MenuKey(theEvent.message & charCodeMask));
  479.             break;
  480.         case activateEvt:
  481.             if (activeFlag & (long)theEvent.modifiers) { /* activate */
  482.                 if (theEvent.message == (long)theWindow) {    
  483.                     HiliteControl(scrollBarCtl, 0); 
  484.                 } 
  485.                 if (theEvent.message == (long)statsWindowPtr) {    
  486.                     HiliteControl(prevButton,0);
  487.                     HiliteControl(nextButton,0);
  488.                 }
  489.             } else { /* inactivate */
  490.                 if (theEvent.message == (long)theWindow) {
  491.                     HiliteControl(scrollBarCtl, 255);
  492.                 }
  493.                 if (theEvent.message == (long)statsWindowPtr) {
  494.                     HiliteControl(prevButton,255);
  495.                        HiliteControl(nextButton,255);                
  496.                 }
  497.             }    
  498.             SetPort(FrontWindow()); /* this is needed */
  499.             break;
  500.        default: if (autoRefresh) refreshProcTable();
  501.       }
  502.    } while(TRUE);
  503.    
  504. }
  505.  
  506.  
  507. void sizeSetup(void) {
  508.       short i;
  509.       
  510.       graphBottom = absBottom-bottomInset;
  511.       graphRange = absBottom - (topInset+bottomInset);
  512.       scaleFactor = (long)memSize/graphRange;
  513.       
  514.       scrollRange = (absBottom/295)*stepsPerScreen;
  515.       
  516.       if (!scrollRange) return;
  517.       
  518.       for(i=0; i<=scrollRange; i++)
  519.          screenOrg[i] = -((long)0xFFFFFFFE & (i*((long)(absBottom)/scrollRange)));
  520. }
  521.  
  522.  
  523. void makeWindow(void) {
  524.     Rect boundsRect;
  525.     
  526.     /* first lets do the STATS window and its controls */
  527.     statsWindowPtr = GetNewWindow(128, &statsWindowRcd, (WindowPtr) -1);
  528.     
  529.     SetRect(&boundsRect, 10, 230, 80, 250);
  530.     nextButton = NewControl(statsWindowPtr, &boundsRect,
  531.                         "\pNext", TRUE, 0, 0,0, pushButProc, 0);
  532.                 
  533.     SetRect(&boundsRect, 110, 230, 180, 250);
  534.     prevButton = NewControl(statsWindowPtr, &boundsRect,
  535.                 "\pPrevious", TRUE, 0, 0,0, pushButProc, 0); 
  536.                 
  537.        /* now the graph window */ 
  538.     SetRect(&limitRect,05,40,5+windowWidth,40+windowLength);
  539.  
  540.     theWindow = NewWindow (&windowRcd,&limitRect,
  541.                    "\pCurrent Processes",1, documentProc,(WindowPtr) -1,1,0);
  542.  
  543.     SetPort(&windowRcd.port);
  544.  
  545.     SetRect(&ctrlRect, windowWidth-16, 0, windowWidth, windowLength);
  546.  
  547.     scrollBarCtl = NewControl(theWindow, &ctrlRect, "\pControl", TRUE, 
  548.                                 0, 0, scrollRange, scrollBarProc, 0); 
  549. }
  550.  
  551.  
  552. void drawStatsWindow(void) {
  553.     unsigned char tar[256];
  554.     union { long value;
  555.             char chars[4]; } converter;
  556.  
  557.     BeginUpdate(statsWindowPtr);
  558.     
  559.     SetPort(&statsWindowRcd.port);
  560.     
  561.     TextSize(9);
  562.     
  563.     MoveTo(10, 20); DrawString("\pProcess name: ");
  564.                     DrawString(InfoRecPtr[selectedProcess]->processName);
  565.     
  566.     MoveTo(10, 35); DrawString("\pStarting address: ");
  567.                     sprintf((char *)tar, "%#lx", InfoRecPtr[selectedProcess]->processLocation);
  568.                     CtoPstr((char *)tar);
  569.                     DrawString(tar);
  570.                     
  571.     MoveTo(10, 50); DrawString("\pLength(size): ");
  572.                     sprintf((char *)tar, "%#ld (%ldK)", (long)(InfoRecPtr[selectedProcess]->processSize),
  573.                     (long)(InfoRecPtr[selectedProcess]->processSize)/1024);
  574.                     CtoPstr((char *)tar);
  575.                     DrawString(tar);
  576.                     
  577.     
  578.     MoveTo(10, 65); DrawString("\pFree bytes in heap: ");
  579.                     sprintf((char *)tar, "%#ld (%ldK)", InfoRecPtr[selectedProcess]->processFreeMem,(InfoRecPtr[selectedProcess]->processFreeMem)/1024);
  580.                     CtoPstr((char *)tar);
  581.                     DrawString(tar);
  582.     
  583.     MoveTo(10, 80); DrawString("\pProcess Type: ");
  584.                     converter.value = InfoRecPtr[selectedProcess]->processType;
  585.                     strncpy((char *)tar, converter.chars, 4);
  586.                     tar[4]='\0'; 
  587.                     CtoPstr((char *)tar);
  588.                     DrawString(tar);
  589.     MoveTo(40, 90);
  590.                     if (InfoRecPtr[selectedProcess]->processMode & modeDeskAccessory)
  591.                             DrawString("\p(Desk Accessory)");
  592.                     if (InfoRecPtr[selectedProcess]->processMode & modeOnlyBackground)
  593.                             DrawString("\p(Background-only application)");
  594.                     
  595.     
  596.     MoveTo(10, 105); DrawString("\pSignature of app file: ");
  597.                     converter.value = InfoRecPtr[selectedProcess]->processSignature;
  598.                     strncpy((char *)tar, converter.chars, 4);
  599.                     tar[4]='\0'; 
  600.                     CtoPstr((char *)tar);
  601.                     DrawString(tar);
  602.     
  603.     MoveTo(10, 120); DrawString("\pAccumulated CPU time: ");
  604.                     sprintf((char *)tar, "%#ld", (InfoRecPtr[selectedProcess]->processActiveTime)/60);
  605.                     CtoPstr((char *)tar);
  606.                     DrawString(tar);
  607.     
  608.  
  609.     MoveTo(10, 135); DrawString("\pSIZE flags:"); 
  610.         MoveTo(30,145);    if (InfoRecPtr[selectedProcess]->processMode & mode32BitCompatible)
  611.                             DrawString("\p32 bit compatible");
  612.         MoveTo(30,155);    if (InfoRecPtr[selectedProcess]->processMode & modeCanBackground)
  613.                             DrawString("\pCan do background processing");
  614.         MoveTo(30,165);    if (InfoRecPtr[selectedProcess]->processMode & modeStationeryAware)
  615.                             DrawString("\pStationery Aware");
  616.  
  617.  
  618.     DrawControls(statsWindowPtr);
  619.     
  620.     EndUpdate(statsWindowPtr);
  621. }
  622.  
  623.  
  624. void readProcTable(void) {
  625.  ProcessSerialNumber process;
  626.  OSErr res;
  627.  ProcessInfoRec recTemp;
  628.  
  629.  process.highLongOfPSN = 0;
  630.  process.lowLongOfPSN = kNoProcess;
  631.  
  632.  numProcs =0;
  633.  
  634.  /* Build up a fake one for the system */
  635.  InfoRec[numProcs].processInfoLength = sizeof(ProcessInfoRec);
  636.  InfoRec[numProcs].processName = "\pSystem";
  637.  InfoRec[numProcs].processAppSpec = NULL;
  638.  InfoRecPtr[numProcs] = &InfoRec[numProcs];
  639.  InfoRec[numProcs].processLocation = *((void **)0x2a6);
  640.  InfoRec[numProcs].processSize = 
  641.      (long)(((THz)InfoRec[numProcs].processLocation)->bkLim) -
  642.      (long)(InfoRec[numProcs].processLocation);
  643.  
  644.  numProcs++;
  645.  
  646.  while( GetNextProcess(&process) == noErr) {
  647.      InfoRec[numProcs].processInfoLength = sizeof(ProcessInfoRec);
  648.      if (InfoRec[numProcs].processName == NULL) 
  649.          InfoRec[numProcs].processName = (void *)NewPtr(40);
  650.      InfoRec[numProcs].processAppSpec = NULL;
  651.      
  652.      if ((res = GetProcessInformation(&process, &(InfoRec[numProcs]))) != noErr) 
  653.         {ExitToShell(); }
  654.      InfoRecPtr[numProcs] = &InfoRec[numProcs];
  655.      numProcs++;
  656.      if (numProcs > maxProcs) break; /* too many to handle */
  657.  }
  658. }
  659.  
  660.  
  661. int compare( const void *n1, const void *n2) {
  662.   long diff;
  663.   ProcessInfoRec **p1, **p2;
  664.   
  665.     p1 = (void *)n1;
  666.     p2 = (void *)n2;
  667.   
  668.     diff = ((long)((*p1)->processLocation)) - 
  669.                (long)((*p2)->processLocation); 
  670.      
  671.     if (diff < 0) return(-1);
  672.     if (diff > 0) return(1);
  673.     return(0);
  674. }
  675.  
  676.  
  677. /* Ensure the entires in the proc InfoRec array are sorted by starting
  678.    address */
  679. void sortProcTable(void) {
  680.   qsort(InfoRecPtr, numProcs, sizeof(char *), compare);
  681. }
  682.  
  683.  
  684. void calcPos(short i, long *top, long *bottom) {
  685.    
  686.   *bottom = graphBottom - (long)(InfoRecPtr[i]->processLocation)/scaleFactor;
  687.   *top = *bottom - (InfoRecPtr[i]->processSize)/scaleFactor;
  688.   
  689. }
  690.  
  691.  
  692. Pattern *(patternArray[3]) = { &gray, <Gray, &dkGray };
  693.  
  694. #define screenTop 0
  695. #define screenBottom windowLength
  696.  
  697. void drawMemDiagram(void) {
  698.     Rect memRect;
  699.     long top, bottom, sizeInK;
  700.     Str255 memTopStr, sizeStr;
  701.     short i;
  702.   
  703.     BeginUpdate(theWindow);
  704.     
  705.     SetPort(&windowRcd.port);
  706.     PenPat(black);
  707.     PenSize(2,2);
  708.  
  709.     /* draw outline */
  710.     SetRect(&memRect, 20,
  711.               topInset-2+graphVertOffset,
  712.               100,
  713.               graphBottom+2+graphVertOffset);
  714.  
  715.     FrameRect(&memRect);
  716.  
  717.     PenSize(1,1);
  718.  
  719.     for(i=0; i< numProcs; i++) {
  720.  
  721.         calcPos(i, &top, &bottom);
  722.     
  723.         top += graphVertOffset;
  724.         bottom += graphVertOffset;
  725.     
  726.         if ((bottom >= screenTop) && (top <= screenBottom)) {
  727.             SetRect(&memRect, 22,
  728.                      top,
  729.                      98,
  730.                      bottom);
  731.                           
  732.             FillRect(&memRect, *patternArray[i%3]);
  733.         
  734.             SetRect(&memRect, 20,
  735.                           top,
  736.                           100,
  737.                           bottom);
  738.                           
  739.             FrameRect(&memRect);
  740.         
  741.             /* draw program name */
  742.             MoveTo(110, bottom-((bottom-top)/2));
  743.             DrawString(InfoRecPtr[i]->processName);
  744.             sizeInK = (InfoRecPtr[i]->processSize)/1024;
  745.             NumToString(sizeInK, sizeStr);
  746.             DrawString("\p (");
  747.             DrawString(sizeStr);
  748.             DrawString("\pK)");
  749.         }  
  750.     }
  751.  
  752.     MoveTo(110,topInset+4+graphVertOffset);
  753.     NumToString(memSize/1024, memTopStr);
  754.     DrawString(memTopStr);
  755.  
  756.     MoveTo(110, graphBottom+4+graphVertOffset);
  757.     DrawString("\p0");
  758.     DrawControls(theWindow);
  759.   
  760.     EndUpdate(theWindow);
  761. }